home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / ODUtils / Except.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-17  |  12.1 KB  |  428 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Except.h
  3.  
  4.     Contains:    Exception handling macros
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12.  
  13. /*
  14.     THEORY OF OPERATION
  15.     
  16.     This is a catch/throw based exception handling package which models
  17.     much of the behavior of native C++ exception handling. (Its macros can
  18.     be redefined to use native exceptions if your compiler supports them.)
  19.     
  20.     Reading this header is not recommended for the faint of heart! Here be
  21.     gnarly macros, setjmp fu, and tangled #ifdefs.
  22.     Please see the recipe document "Using Exceptions" for details presented
  23.     in a human-readable fashion.
  24.     
  25.     If the symbol _NATIVE_EXCEPTIONS_ is predefined, native C++ exception
  26.     handling will be used.
  27.     If the symbol _ASM_XTRY_ is predefined, a special assembly-coded
  28.     version of _xTry will be called, which makes the calling code for TRY
  29.     shorter and slightly faster. (This feature still in progress...)
  30. */
  31.  
  32. #ifndef _EXCEPT_
  33. #define _EXCEPT_
  34.  
  35. #ifndef _ODTYPES_
  36. #include "ODTypes.h"
  37. #endif
  38.  
  39. #ifndef FWODEXCE_H            // [HLX]
  40. #include "FWODExce.h"        // [HLX]
  41. #endif                        // [HLX]
  42.  
  43. #ifndef _ERRORDEF_
  44.     #ifdef __cplusplus
  45.     #include "ErrorDef.xh"    // Clients probably need the error codes as well
  46.     #else
  47.     #include "ErrorDef.h"
  48.     #endif
  49. #endif
  50.  
  51. #ifndef __SETJMP__
  52. #include <setjmp.h>
  53. #endif
  54.  
  55. #ifdef __LIBRARYMANAGER__
  56. #error "Please don't include both Except.h and LibraryManager.h"
  57. #endif
  58.  
  59.  
  60. #ifdef _OD_IMPL_SHARE_UTILS_
  61. #pragma import on
  62. #endif
  63.  
  64. #ifdef __cplusplus
  65. extern "C" {
  66. #endif
  67.  
  68.  
  69. //=====================================================================================
  70. // ODVolatile
  71. //=====================================================================================
  72.  
  73. // Any variable or parameter that is modified in a TRY block and used in the
  74. // CATCH block must be declared as volatile or it may have an incorrect value
  75. // in the CATCH block.
  76. // Since not all compilers support the 'volatile' keyword, use this instead;
  77.  
  78. #ifndef _NATIVE_EXCEPTIONS_
  79. #define ODVolatile(x)    ((void) &x)
  80. #else
  81. #define ODVolatile(x)    /*no need for this with native exceptions*/
  82. #endif
  83.  
  84. //=====================================================================================
  85. // Exception Handling Macros (native C++ exceptions)
  86. //=====================================================================================
  87.  
  88. #ifdef _NATIVE_EXCEPTIONS_
  89.  
  90. #define ErrorCode()                (_exception.error)
  91. #define ErrorMessage()            (_exception.message)
  92. #define SetErrorCode(ERR)        (_exception.error=(ERR))
  93. #define SetErrorMessage(MSG)    (strcpy(_exception.error,(MSG))
  94.  
  95. #define TRY                                                    \
  96.                 try {
  97.  
  98. #define CATCH_ALL                                            \
  99.                 } catch(ODException _exception) {
  100.  
  101. #define RERAISE                                                \
  102.                 throw
  103.  
  104. #define SET_SOM_EXCEPTION(EV)                                \
  105.                 ODSetSOMException(EV,_exception)
  106.  
  107. void _xSetSOMException(Environment*,ODException&);
  108.  
  109. #define ENDTRY                                                \
  110.                 }
  111.  
  112. /* CATCH( ) will not work with native exceptions. Don't use it! */
  113.  
  114.  
  115. //=====================================================================================
  116. // Exception Handling Macros (emulated)
  117. //=====================================================================================
  118.  
  119. #else /*not _NATIVE_EXCEPTIONS*/
  120.  
  121. //#define ErrorCode()                 (_except.fError)                        // [HLX]
  122. #define ErrorCode()                 (_except.GetPlatformError())            // [HLX]
  123.  
  124. //#define ErrorMessage()            (_except.fODException ?_except.fODException->message :kODNULL)    // [HLX]
  125. #define ErrorMessage()                (kODNULL)                                                        // [HLX]
  126.  
  127. #define SetErrorCode(ERR)            (_xSetErrorCode(&_except,(ERR)))        // [HLX]  Jim, what should we do?
  128. #define SetErrorMessage(MSG)        (_xSetErrorMessage(&_except,(MSG))        // [HLX]  Jim, what should we do?
  129.  
  130. #ifndef _ASM_XTRY_
  131.     #define _setjmp_xTry(EX)        setjmp(*_xTry(EX))
  132.     #define _setjmp_xTryEv(EX,EV)    setjmp(*_xTryEv(EX,EV))
  133. #endif
  134.  
  135. #define TRY FW_TRY                                                        // [HLX]
  136. /*                                                                        // [HLX]
  137. #define TRY                                                 \
  138.     {                                                        \
  139.         ODExceptionFrame _except;                            \
  140.         ODVolatile(_except);                                \
  141.         if (_setjmp_xTry(&_except) == 0)                    \
  142.         {
  143. */                                                                        // [HLX]
  144.         
  145. #define CATCH_ALL FW_CATCH_BEGIN FW_CATCH_REFERENCE(FW_XException, _except)    // [HLX]
  146. /*                                                                            // [HLX]
  147. #define CATCH_ALL                                            \
  148.         }                                                    \
  149.         else                                                \
  150.         { 
  151. */                                                                            // [HLX]
  152.         
  153.         
  154. #define RERAISE FW_THROW_SAME()                                                // [HLX]
  155. /*                                                                            // [HLX]
  156. #define RERAISE                                                \
  157.         _xReraise(&_except)
  158. */                                                                            // [HLX]
  159.  
  160. #define SET_SOM_EXCEPTION(EV)                                \
  161.         _xSetSOMException(EV,&_except)
  162.         
  163. #define ENDTRY    FW_CATCH_END                                                // [HLX]
  164. /*                                                                            // [HLX]
  165. #ifdef __cplusplus    
  166. #define ENDTRY                                                \
  167.         }                                                    \
  168.     }
  169. #else // C version:
  170. #define ENDTRY                                                \
  171.         }                                                    \
  172.         _xPop(&_except);                                    \
  173.     }
  174. #endif
  175. */                                                                            // [HLX]
  176.  
  177. // CATCH( ) is not compatible with native C++ exceptions.
  178. // Its use is discouraged.
  179. //#define CATCH(e)                                            \
  180. //        } else if (_except.fError==(e)) { 
  181.         
  182.         
  183. #endif /*_NATIVE_EXCEPTIONS*/
  184.  
  185. //=====================================================================================
  186. // Raising Exceptions
  187. //=====================================================================================
  188.  
  189. //void THROW(ODError error);                // [HLX]
  190. //void THROW_IF_ERROR(ODError error);        // [HLX]
  191. //void THROW_IF_NULL(void* value);            // [HLX]
  192.  
  193. inline void THROW(ODError error)
  194.                             {FW_Failure(error); }
  195. inline void THROW_IF_ERROR(ODError error)
  196.                             {FW_FailOnError(error); }
  197. inline void THROW_IF_NULL(void* value)
  198.                             {if (!value) FW_Failure(kODErrOutOfMemory); }
  199.  
  200. // Optional message parameters (ignored in nondebug build):
  201. #if ODDebug
  202. void THROW_IF_ERROR_M(ODError error, const char* msg);
  203. void THROW_M(ODError error, const char* msg);
  204. void THROW_IF_NULL_M(void* value, const char* msg);
  205. #else
  206. #define THROW_IF_ERROR_M(ERR,MSG)    THROW_IF_ERROR(ERR)
  207. #define THROW_M(ERR,MSG)            THROW(ERR)
  208. #define THROW_IF_NULL_M(ERR,MSG)    THROW_IF_NULL(ERR)
  209. #endif
  210.  
  211. #ifdef __cplusplus
  212. }
  213. // Overloaded C++ equivalents:
  214. inline void THROW_IF_ERROR(ODError error, const char* /*msg*/)     // [HLX]
  215.                             {THROW_IF_ERROR_M(error,msg);}
  216. inline void THROW(ODError error, const char*  /*msg*/)            // [HLX]
  217.                             {THROW_M(error,msg);}
  218. inline void THROW_IF_NULL(void* value, const char*  /*msg*/)    // [HLX]
  219.                             {THROW_IF_NULL_M(value,msg);}
  220. inline void THROW_IF_NULL(void* value, ODError error)
  221.                             {if ( value == kODNULL ) THROW(error);}
  222. extern "C" {
  223. #endif
  224.  
  225. // Call BreakOnThrow(TRUE) to break into the debugger whenever THROW is called.
  226. // (The call returns the previous value of the setting.)
  227. ODBoolean BreakOnThrow( ODBoolean brk );
  228.  
  229.  
  230. //=====================================================================================
  231. // SOM Exception Utilities
  232. //=====================================================================================
  233.  
  234. // This modified TRY block should be used in SOM methods. It's just like a
  235. // regular TRY...CATCH_ALL...ENDTRY except that the exception code will be
  236. // stored in the Environment. Needless to say you should _not_ reraise!
  237. // You should also not make any SOM calls after the SOM_ENDTRY, nor declare any
  238. // Destructo objects before the SOM_TRY.
  239.  
  240. #ifdef _NATIVE_EXCEPTIONS_
  241.  
  242. #define SOM_TRY                                                 \
  243.             TRY
  244.             
  245. #define SOM_CATCH_ALL                                            \
  246.             CATCH_ALL {                                            \
  247.                 
  248. #define SOM_ENDTRY                                                \
  249.             } ODSetSOMException(ev,_exception);                    \
  250.             ENDTRY
  251.             
  252. #else /*not _NATIVE_EXCEPTIONS_*/
  253.  
  254. #define SOM_TRY                                                 \
  255.         {                                                        \
  256.             ODExceptionFrame _except;                            \
  257.             ODVolatile(_except);                                \
  258.             if (_setjmp_xTryEv(&_except,ev) == 0)                \
  259.             {
  260.  
  261. #define SOM_CATCH_ALL                                            \
  262.             CATCH_ALL
  263. #define SOM_ENDTRY                                                \
  264.             ENDTRY
  265.  
  266. #endif /*_NATIVE_EXCEPTIONS_*/
  267.  
  268.  
  269. // ODSetSOMException stores an OD error code in the environment.
  270. // ODGetSOMException returns the OD error code (if any) from an environment.
  271.  
  272. #ifdef __cplusplus
  273. void    ODSetSOMException( Environment*, ODError, const char *msg =kODNULL );
  274. #else
  275. void    ODSetSOMException( Environment*, ODError, const char *msg );
  276. #endif
  277.  
  278. #ifdef _NATIVE_EXCEPTIONS_
  279. } // end extern C
  280. void    ODSetSOMException( Environment*, ODException& );
  281. extern "C" {
  282. #endif
  283.  
  284. ODError    ODGetSOMException( Environment *ev );
  285.  
  286. // CHECK_ENV throws an exception if the environment indicates an error.
  287.  
  288. void    CHECK_ENV( Environment* );
  289.  
  290. // SOMCHKEXCEPT is a macro that is called in a .xh file if the ev variable
  291. // indicates an exception is set.
  292. //#define SOMCHKEXCEPT {CHECK_ENV(ev);}        [HLX]
  293.  
  294.  
  295. //=====================================================================================
  296. // Obsolete Exception Utilities
  297. //=====================================================================================
  298.  
  299. /*  FN_CATCH and SOM_CATCH are discouraged (not compatible with native C++
  300.     exceptions) but still implemented for the time being to give people time
  301.     to convert their code. */
  302.  
  303. #if defined(__MWERKS__) || defined(__SC__)
  304.     extern void FN_CATCH_DIDNT_RETURN( );
  305.     /* This function is purposely declared but never defined. Due to the setup of
  306.        the for loop in FN_CATCH and SOM_CATCH, a failure to end the block with a
  307.        return statement will cause the call to FN_CATCH_DIDNT_RETURN not to be
  308.        dead stripped, resulting in a link error. This will help catch this nasty
  309.        coding error. */
  310. #else
  311.     // Other compilers may not dead-strip properly.
  312.     #define FN_CATCH_DIDNT_RETURN() /**/
  313. #endif
  314.  
  315. #define FN_CATCH                                            \
  316.         ODExceptionFrame _except;                            \
  317.         ODVolatile(_except);                                \
  318.         if (_setjmp_xTry(&_except) != 0)                    \
  319.             for( ; true; FN_CATCH_DIDNT_RETURN() )
  320.  
  321. #define SOM_CATCH                                            \
  322.         ODExceptionFrame _except;                            \
  323.         ODVolatile(_except);                                \
  324.         if (_setjmp_xTryEv(&_except,ev) != 0)                \
  325.             for( ; true; FN_CATCH_DIDNT_RETURN() )
  326.  
  327.  
  328. //=====================================================================================
  329. // Finally, the Exception Handler (ODExceptionFrame struct)
  330. //=====================================================================================
  331.  
  332.  
  333. #ifndef _NATIVE_EXCEPTIONS_
  334.  
  335. #ifdef __cplusplus
  336. class Destructo;    // forward declarations for use below
  337. struct ODExceptionFrame;
  338. void _xPop(ODExceptionFrame*);
  339. }    // end of extern "C" block
  340. #else
  341. typedef struct ODExceptionFrame ODExceptionFrame;
  342. typedef struct Destructo Destructo;        // Not used in C but must declare anyway
  343. #endif
  344.  
  345. struct ODExceptionFrame
  346. {
  347.     ODExceptionFrame*    fPrev;
  348.     ODException*        fODException;
  349.     ODError                fError;
  350.     Environment*        fEv;
  351.     Destructo*            fDestructoList;
  352.     jmp_buf                fBuffer;
  353.     // If you change the size of this struct you _must_ update Except.s and Except.a
  354.     // accordingly!
  355. #ifdef __cplusplus
  356.     void Throw( ODError err, const char* msg, ODException *x =kODNULL );
  357.     inline ~ODExceptionFrame( )    {_xPop(this);}
  358. #endif
  359. };
  360.  
  361. #ifdef __cplusplus
  362. extern "C" {
  363. #endif
  364.  
  365. typedef struct ODExceptionFrame ODExceptionFrame;
  366.  
  367. #ifdef _ASM_XTRY_
  368.     int _setjmp_xTry( ODExceptionFrame* );
  369.     int _setjmp_xTryEv( ODExceptionFrame*, Environment* );
  370. #else
  371.     jmp_buf* _xTry( ODExceptionFrame* );
  372.     jmp_buf* _xTryEv( ODExceptionFrame*, Environment* );
  373. #endif
  374.  
  375. void _xReraise( ODExceptionFrame* );
  376. void _xSetSOMException(Environment*,ODExceptionFrame*);
  377. void _xPop( ODExceptionFrame* );
  378. void _xSetErrorCode( ODExceptionFrame*, ODError );
  379. void _xSetErrorMessage( ODExceptionFrame*, const char* );
  380.  
  381. #endif /*_NATIVE_EXCEPTIONS_*/
  382.  
  383.  
  384. #ifdef __cplusplus
  385. }    // end of extern "C" block
  386. #endif
  387.  
  388.  
  389. //=====================================================================================
  390. // Destructo, a C++ base class for auto-destruct objects
  391. //=====================================================================================
  392.  
  393. #ifdef __cplusplus
  394.  
  395. class Destructo
  396. {
  397. //#ifndef _NATIVE_EXCEPTIONS_  // [HLX]
  398. protected:
  399.     Destructo( ) {};// [HLX]
  400.     
  401. public:
  402.     virtual ~Destructo( ){};// [HLX]
  403.     
  404. private:
  405.     Destructo* EmergencyDestruct( ){return this;};// [HLX]
  406.     Destructo *fPrevDestructo;
  407.     friend class ODExceptionFrame;
  408.  
  409. //#endif /*_NATIVE_EXCEPTIONS_*/ // [HLX]
  410.     static void* operator new( size_t );    // Make it illegal to allocate on heap
  411.                                             // In future could use alloca??
  412.                                             
  413.     private: // disallow these:
  414.     Destructo(const Destructo& );
  415.     void operator=(const Destructo& );
  416.     // Bitwise assigning one destructo to another smashes
  417.     // fPrevDestructo with potentially unpleasant effects.
  418. };
  419.  
  420. #endif /*__cplusplus*/
  421.  
  422. #ifdef _OD_IMPL_SHARE_UTILS_
  423. #pragma import off
  424. #endif
  425.  
  426.  
  427. #endif // _EXCEPT_
  428.